package com.test.system.controller;


import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpUtil;
import com.xingluo.system.permission.entity.SysMenu;
import com.xingluo.system.permission.entity.SysUser;
import com.xingluo.system.permission.service.SysMenuService;
import com.xingluo.system.permission.service.SysUserService;
import com.xingluo.system.satoken.AuthUtils;
import com.xingluo.tools.captcha.CaptchaUtils;
import com.xingluo.tools.exception.ServiceException;
import com.xingluo.tools.ip.utils.IpUtils;
import com.xingluo.tools.result.CodeMsg;
import com.xingluo.tools.result.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 管理员登录、登出操作
 *
 * @author qiuyongjuan@pku.org.cn
 * @since 2022-03-16
 */
@Slf4j
@Tag(name="登录管理接口")
@RestController
@RequestMapping("/auth")
public class LoginController {

    @Resource
    private CaptchaUtils captchaUtils;

    @Resource
    protected SysUserService sysUserService;

    @Resource
    private StpInterface stp;

    @Resource
    protected SysMenuService menuService;

    /**
     * 获取验证码
     */
    @Operation(summary = "获取验证码", description = "获取验证码")
    @GetMapping("/code")
    public Result captchaImage() {
        return captchaUtils.generateMathImageCode();
    }

    /**
     * 登录方法
     */
    @Operation(summary = "登录方法", description = "登录方法")
    @PostMapping("/login")
    public Result login(@RequestParam("username") String username, @RequestParam("password") String password,
                        @RequestParam("code") String code, @RequestParam("uuid") String uuid) {
        //校验验证码，若有错误抛出CaptchaException异常，可在统一异常处理中处理
        captchaUtils.validateImageCode(code, uuid);
        SysUser user = sysUserService.getUserByUsername(username);
        if (user == null) {
            throw new ServiceException("用户名错误");
        } else if (!AuthUtils.matchesPassword(password, user.getPassword())) {
            // todo 异步记录登录日志
            throw new ServiceException("密码错误");
        } else {
            // 登录并返回tokenName、token、refreshToken
            Result result = AuthUtils.login(user.getId(), user.getScopeId(), Map.of(
                    "username", user.getUserName(),
                    "ip", IpUtils.getHostIp()
            ), 12);

            System.out.println(AuthUtils.getUserScopeId());
            // todo 异步处理登录日志
            return result;
        }
    }

    /**
     * 获取登录用户信息
     *
     * @return 用户信息
     */
    @Operation(summary = "获取登录用户信息", description = "获取登录用户信息")
    @GetMapping("getInfo")
    public Result getLoginUserInfo() {
        long userId = StpUtil.getLoginIdAsLong();
        SysUser user = sysUserService.getById(userId);
        // 角色集合，使用框架的stp，则使用sys_user表关联角色
        List<String> roles = stp.getRoleList(userId, "");
        // 权限集合，使用框架的stp，则使用sys_user表关联权限
        List<String> permissions = stp.getPermissionList(userId, "");
        Result result = Result.success();
        result.put("user", user);
        result.put("roles", roles);
        result.put("permissions", permissions);
        return result;
    }

    /**
     * 刷新token
     */
    @Operation(summary = "刷新token", description = "刷新token")
    @PostMapping("/refreshToken")
    public Result refreshToken(@RequestParam("refreshToken") String refreshToken) {
        SysUser user = sysUserService.getById(AuthUtils.verifyRefreshToken(refreshToken));
        if (user == null) {
            return Result.error(CodeMsg.REFRESH_TOKEN_ERROR);
        }
        return AuthUtils.refreshToken(user.getId(), user.getScopeId(), Map.of(
                        "username", user.getUserName(),
                        "ip", IpUtils.getHostIp()
                ));
    }

    /**
     * 获取路由信息
     *
     * @return 路由信息
     */
    @Operation(summary = "获取路由信息", description = "获取路由信息")
    @GetMapping("/getRouters")
    public Result getRouters() {
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(AuthUtils.getUserId());
        return Result.success(menuService.buildMenus(menus));
    }

    /**
     * 管理员登出
     */
    @Operation(summary = "管理员登出", description = "管理员登出")
    @GetMapping("/logout")
    public Result logout(HttpServletRequest request) {
        String ip = IpUtils.getIpAddr(request);
        AuthUtils.logout();
        return Result.success("退出成功");
    }
}
